#ifndef _ACTION_H_
#define _ACTION_H_

#include "struct.h"

enum e_action {
  SHIFT,
  ACCEPT,
  REDUCE,
  ERROR,
  SSCONFLICT,              /* A shift/shift conflict */
  SRCONFLICT,              /* Was a reduce, but part of a conflict */
  RRCONFLICT,              /* Was a reduce, but part of a conflict */
  SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */
  RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */
  NOT_USED,                /* Deleted by compression */
  SHIFTREDUCE              /* Shift first, then reduce */
};

/* Every shift or reduce operation is stored as one of the following */
class Action {
 public:
  Action(e_action t, Symbol* sym, char* arg):type(t),sp(sym)
  {
    if (type == SHIFT) {
      this->x.stp = (State *)arg;
    } else {
      this->x.rp = (Rule *)arg;
    }
  }
  Symbol *sp;       /* The look-ahead symbol */
  enum e_action type;
  union {
    State *stp;     /* The new state, if a shift */
    Rule *rp;       /* The rule, if a reduce */
  } x;
};

struct lookahead_action {
  int lookahead;             /* Value of the lookahead token */
  int action;                /* Action to take on the given lookahead */
};

struct acttab {
  int nAction;                 /* Number of used slots in aAction[] */
  int nActionAlloc;            /* Slots allocated for aAction[] */
  struct lookahead_action
    *aAction,                  /* The yy_action[] table under construction */
    *aLookahead;               /* A single new transaction set */
  int mnLookahead;             /* Minimum aLookahead[].lookahead */
  int mnAction;                /* Action associated with mnLookahead */
  int mxLookahead;             /* Maximum aLookahead[].lookahead */
  int nLookahead;              /* Used slots in aLookahead[] */
  int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */
};

void Action_sort(std::list<Action*>&);

void Action_add(std::list<Action*>& app, enum e_action type, Symbol *sp, char *arg);

void acttab_action(acttab *p, int lookahead, int action);

int acttab_insert(acttab *p);

/* Return the number of entries in the yy_action table */
#define acttab_size(X) ((X)->nAction)

/* The value for the N-th entry in yy_action */
#define acttab_yyaction(X,N)  ((X)->aAction[N].action)

/* The value for the N-th entry in yy_lookahead */
#define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead)

acttab *acttab_alloc(void);

#endif // _ACTION_H_
